package lib

import (
	"GameServer/Common/utils"
	"fmt"

	"GameServer/Common/data"
	"GameServer/Game/errors"
	"GameServer/Game/m"
)

func NewHideShop(u *m.User) (r *m.HideShop, err error) {
	r, err = newHideShop(u.Pos.LockBlockTid)
	if err != nil {
		return
	}
	r.Uid = u.Uid
	return
}

func newHideShop(lockBlockId int64) (r *m.HideShop, err error) {
	now := utils.TNow()
	endTime := now.Unix() + data.HideShopEnum.LifeTime
	r = &m.HideShop{
		EndTime:  endTime,
		LastTime: endTime, //now.Unix(),
		FireNum:  0,
		FreshNum: 0,
		Goods:    make(map[int64]*m.HideShopGoods, 0),
		AdGoods:  make(map[int64]*m.HideShopGoods, 0),
	}
	//nextTime, err := r.ReFreshNextTime(endTime + data.HideShopEnum.NoFreshTime)
	_, _, _, matchNextTime, err := r.CheckInHideShopTime(now.Unix())
	if err != nil {
		return
	}
	r.NextTime = matchNextTime
	hgoods, hgoodsAd, err := hideShopGoods(lockBlockId)
	if err != nil {
		return
	}
	r.Goods = hgoods
	r.AdGoods = hgoodsAd
	return
}

func GmNewHideShop(u *m.User) (err error) {
	newHs := &m.HideShop{
		Uid:     u.Uid,
		Goods:   make(map[int64]*m.HideShopGoods, 0),
		AdGoods: make(map[int64]*m.HideShopGoods, 0),
	}
	nowTime := utils.TNow().Unix()
	_, _, _, matchNextTime, _ := newHs.CheckInHideShopTime(nowTime)
	reflashGmHideShop := func(u *m.User, theHideShop *m.HideShop, nextTime int64) {
		theHideShop.Uid = u.Uid
		theHideShop.LastTime = nowTime
		theHideShop.EndTime = int64(nowTime + data.HideShopEnum.LifeTime)
		theHideShop.NextTime = nextTime
		//fmt.Printf("endTime:%d", int64(newHs.EndTime))
		theHideShop.FireNum = 15
		theHideShop.FreshNum = 0
		theHideShop.IsSpecial = 1
		hgoods, hgoodsAd, err := hideShopGoods(u.Pos.LockBlockTid)
		if err == nil {
			theHideShop.Goods = hgoods
			theHideShop.AdGoods = hgoodsAd
		}
		u.UpdateHideShop(theHideShop)
	}
	reflashGmHideShop(u, newHs, matchNextTime)
	return nil
}

func hideShopGoods(lockBlockId int64) (rGoods map[int64]*m.HideShopGoods, rGoodsAd map[int64]*m.HideShopGoods, err error) {
	var num int64 = 0
	list, ok := data.GetAllDatas("HideShops")
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, "没有神秘商店配置")
		return
	}

	mShop := make(map[int64]data.HideShop, 0)

	for _, item := range list {
		itemv := item.(data.HideShop)
		mShop[int64(itemv.Id)] = itemv
	}

	getshopGoods := func(levelDoor int64, goodsList []data.HideShopGoods) (r *m.Goods) {
		var baseGoods m.Goods
		for _, item := range goodsList {
			if item.LevelDoor == 0 {
				baseGoods = m.Goods{Tid: int64(item.GoodsId), Num: int64(item.Num)}
			}
			if int64(item.LevelDoor) == levelDoor {
				return &m.Goods{Tid: int64(item.GoodsId), Num: int64(item.Num)}
			}
		}
		return &baseGoods
	}

	rGoods = make(map[int64]*m.HideShopGoods, 0)
	for _, item := range mShop {
		if num >= data.HideShopEnum.GoodsNum {
			break
		}
		num++
		hgoods := &m.HideShopGoods{
			Id:    int64(item.Id),
			Num:   int64(item.LimitNum),
			Goods: getshopGoods(lockBlockId, item.Goods),
		}
		rGoods[int64(item.Id)] = hgoods
	}

	var numAddGoods int64 = 0
	listAddGoods, ok := data.GetAllDatas("HideShopAdShopGoods")
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, "配置表读取异常：HideShopAdShopGoods")
		return
	}
	mShopAd := make(map[int64]data.HideShopAdShopGood, 0)
	for _, item := range listAddGoods {
		itemv := item.(data.HideShopAdShopGood)
		mShopAd[int64(itemv.Id)] = itemv
	}

	rGoodsAd = make(map[int64]*m.HideShopGoods, 0)
	for _, item := range mShopAd {
		if numAddGoods >= data.HideShopEnum.AdGoodsNum {
			break
		}
		numAddGoods++
		hgoods := &m.HideShopGoods{
			Id:    int64(item.Id),
			Num:   int64(item.LimitNum),
			Goods: getshopGoods(lockBlockId, item.Goods),
		}
		rGoodsAd[int64(item.Id)] = hgoods
	}
	/*
		for _, item := range listAddGoods {
			if numAddGoods >= data.HideShopEnum.AdGoodsNum {
				break
			}
			numAddGoods++
			itemv := item.(data.HideShopAdShopGood)
			hgoods := &m.HideShopGoods{
				Id:    int64(itemv.Id),
				Num:   int64(itemv.LimitNum),
				Goods: getshopGoods(lockBlockId, itemv.Goods),
			}
			rGoodsAd[int64(itemv.Id)] = hgoods
		}
	*/

	return
}

// 设置神秘商店交互次数
func SetHideShopFireNum(u *m.User, targetFireNum int64) {
	hs := u.HideShop()
	if hs != nil {
		hs.SetFireNum(targetFireNum)
	}
}

// 获取神秘商店
func GetHideShop(u *m.User) (hs *m.HideShop, err error) {
	hs = u.HideShop()
	now := utils.TNow()
	inTime, matchBeginTime, matchEndTime, matchNextTime, err := hs.CheckInHideShopTime(now.Unix())
	if err != nil {
		return
	}
	//检查是否达到交互次数条件，触发重置
	var isMatchFireNum bool = false
	if hs.FireNum >= data.HideShopEnum.FireNum {
		isMatchFireNum = true
		hs.SetFireNum(0)
	}

	if inTime {
		//1.读取上次激活神秘商店的结束时间，在当前时间段的话，判断“上次神秘商店”就是“本次神秘商店”或者是额外触发的神秘商店抵消了，不需要刷新
		//fmt.Printf("InTime lastTime = %d,beginT = %d,endT = %d", hs.LastTime, matchBeginTime, matchEndTime)
		if hs.LastTime >= matchBeginTime && hs.LastTime <= matchEndTime {
			// Goods：普通商品 AdGoods：广告道具 为空
			if hs.Goods == nil || len(hs.Goods) == 0 || hs.AdGoods == nil || len(hs.AdGoods) == 0 {
				//fmt.Println(" 1.时间内      道具为空，新建")
				newHs, err := NewHideShop(u)
				if err != nil {
					return hs, err
				}
				newHs.LastTime = matchEndTime  //复写 lastTime
				newHs.EndTime = matchEndTime   //复写 endTime
				newHs.NextTime = matchNextTime //复写 nextTime
				newHs.IsSpecial = 0
				u.UpdateHideShop(newHs)
				return newHs, nil
			} else {
				if isMatchFireNum {
					hs.IsSpecial = 0
					u.UpdateHideShop(hs)
					//fmt.Println(" 2.时间内.isMatchFireNum")
				}
				//fmt.Println(" 3.时间内")
				return hs, nil
			}
		} else {
			//2.上次激活神秘商店的结束时间，不在匹配时间段内，判断“上次神秘商店”是旧的------执行刷新
			//3.满足交互次数条件 ? 本来在时间内就要触发，交互次数也要在时间内才能触发，两个本应该是互斥的
			if isMatchFireNum {

			}
			newHs, err := NewHideShop(u)
			if err != nil {
				return hs, err
			}
			newHs.LastTime = matchEndTime  //复写 lastTime
			newHs.EndTime = matchEndTime   //复写 endTime
			newHs.NextTime = matchNextTime //复写 nextTime
			u.UpdateHideShop(newHs)
			return newHs, nil
		}
	} else {
		//不在时间段内，不允许刷新
		if isMatchFireNum {
			newHs, err := NewHideShop(u)
			if err != nil {
				return hs, err
			}
			newHs.LastTime = now.Unix()                             //复写 lastTime
			newHs.EndTime = now.Unix() + data.HideShopEnum.LifeTime //复写 endTime
			newHs.NextTime = matchNextTime                          //复写 nextTime
			newHs.IsSpecial = 1
			u.UpdateHideShop(newHs)
			return newHs, nil
		}
		return
	}
	/*
		if now.Unix() > hs.NextTime && now.Unix() > hs.EndTime {
			fmt.Printf("神秘商店----1>,uid:%s, nextTime: %d, endTime: %d now:%s\n", u.Uid, hs.NextTime, hs.EndTime, utils.TimeToLayout(now))
			log.WithFields(log.Fields{
				"uid":      u.Uid.Hex(),
				"Name":     u.Name,
				"nextTime": hs.NextTime,
				"EndTime":  hs.EndTime,
				"FireNum":  hs.FireNum,
				"method":   "GetHideShop",
			}).Debug("---神秘商店1---")
			_, err = hs.ReFreshNextTime(now.Unix())
			if err != nil {
				return
			}
		}

		//	已经达到下次刷新
		if hs.AutoReFresh && (now.Unix() == hs.NextTime || (now.Unix() > hs.NextTime && now.Unix() < hs.NextTime+5)) {
			fmt.Printf("神秘商店----2已经达到下次刷新>,uid:%s, nextTime: %d, endTime: %d, autoRefresh:%v now:%s\n", u.Uid, hs.NextTime, hs.EndTime, hs.AutoReFresh, utils.TimeToLayout(now))
			log.WithFields(log.Fields{
				"uid":      u.Uid.Hex(),
				"Name":     u.Name,
				"nextTime": hs.NextTime,
				"EndTime":  hs.EndTime,
				"FireNum":  hs.FireNum,
				"method":   "GetHideShop",
			}).Debug("---神秘商店2-已经达到下次刷新--")
			newHs, err := NewHideShop(u)
			if err != nil {
				return hs, err
			}
			newHs.FireNum = hs.FireNum
			u.UpdateHideShop(newHs)
			return newHs, nil
		}

		// 放火次数达到
		if hs.FireNum >= data.HideShopEnum.FireNum {
			fmt.Printf("神秘商店----3放火次数达到>,uid:%s,  hs.FireNum: %d, now:%s\n", u.Uid, hs.FireNum, utils.TimeToLayout(now))
			log.WithFields(log.Fields{
				"uid":      u.Uid.Hex(),
				"Name":     u.Name,
				"nextTime": hs.NextTime,
				"EndTime":  hs.EndTime,
				"FireNum":  hs.FireNum,
				"method":   "GetHideShop",
			}).Debug("---神秘商店3-放火次数达到--")
			newHs, err := NewHideShop(u)
			if err != nil {
				return hs, err
			}
			u.UpdateHideShop(newHs)
			return newHs, nil
		}
		return*/
}

//
func HideShopReFresh(u *m.User) (hs *m.HideShop, uProp *m.UpdateProp, err error) {
	hs = u.HideShop()
	nowTime := utils.TNow().Unix()
	if hs.EndTime <= nowTime {
		err = errors.NewErrcode(data.Errcode.ServerErr, "神秘商店已经结束，不能刷新")
		return hs, nil, err
	}
	list, ok := data.GetAllDatas("HideShopRefreshCosts")
	if !ok || len(list) == 0 {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, "没有神秘商店刷新消耗配置")
		return
	}

	costItem := m.BaseKV{Key: data.GlobalEnum.Diamond}
	var lastCostItem data.HideShopRefreshCost
	for _, item := range list {
		itemv := item.(data.HideShopRefreshCost)
		if int64(itemv.Times) > int64(lastCostItem.Times) {
			lastCostItem = itemv
		}
		if int64(itemv.Times) == (hs.FreshNum + 1) {
			costItem.Val = int64(itemv.Diamon)
		}
	}
	if hs.FreshNum >= int64(lastCostItem.Times) {
		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("没有刷新次数：freshNum=%d", hs.FreshNum))
		return
	}

	uProp, err = Cost("HideShopReFresh", u, []m.BaseKV{costItem})
	if err != nil {
		return
	}
	// newHs, err := NewHideShop(u)
	// if err != nil {
	// 	return
	// }
	// newHs.EndTime = hs.EndTime
	// newHs.NextTime = hs.NextTime
	// newHs.FireNum = hs.FireNum
	// newHs.FreshNum = hs.FreshNum + 1
	// u.UpdateHideShop(newHs)
	// hs = newHs
	hgoods, hgoodsAd, err := hideShopGoods(u.Pos.LockBlockTid)
	if err != nil {
		return
	}
	hs.Goods = hgoods
	hs.AdGoods = hgoodsAd
	hs.FreshNum = hs.FreshNum + 1
	u.UpdateHideShop(hs)
	return
}

// 购买物品
func HideShopBuyGoods(from string, u *m.User, id int64, num int64, code int64, PSend func(interface{}) error) (gid int64, uProp *m.UpdateProp, resGoods []*m.Goods, boxResList []*m.BoxRes, err error) {
	if code == 0 {
		gid, uProp, resGoods, boxResList, err := HideShopBuyGoodsNormal(from, u, id, num, code, PSend)
		return gid, uProp, resGoods, boxResList, err
	} else if code == 1 {
		gid, uProp, resGoods, boxResList, err := HideShopBuyGoodsAd(from, u, id, num, code, PSend)
		// 成就，记录观看广告
		AddAchievProgress(u, data.AchievementType.Watch_ads, 1)
		return gid, uProp, resGoods, boxResList, err
	}
	return
}

func HideShopBuyGoodsNormal(from string, u *m.User, id int64, num int64, code int64, PSend func(interface{}) error) (gid int64, uProp *m.UpdateProp, resGoods []*m.Goods, boxResList []*m.BoxRes, err error) {
	if num <= 0 {
		return
	}
	hs := u.HideShop()

	hsGoods, ok := hs.GetHideShopGoods(id)
	if !ok {
		err = errors.NewErrcode(data.Errcode.NotFound, "商城没有这个物品")
		return
	}

	if hsGoods.Num < num {
		err = errors.NewErrcode(data.Errcode.NoRes, "商城物品数量不足")
		return
	}

	tpl, ok := data.Get("HideShops", uint64(id))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有神秘商店物品配置，id:%d", id))
		return
	}
	hsT := tpl.(data.HideShop)
	hideShopPrice, ok := data.Get("HideShopPrices", uint64(hsT.Price))
	if !ok {
		err = errors.NewErrcode(data.Errcode.NotFound, "HideShopPrices没有这个物品")
		return
	}
	hideShopPriceTemp := hideShopPrice.(data.HideShopPrice)
	hideShopPriceValue := hideShopPriceTemp.Price
	var priceValue data.HideShopGoods
	if len(hideShopPriceValue) == 1 {
		priceValue = hideShopPriceValue[0]
	} else {
		for _, value := range hideShopPriceValue {
			if value.LevelDoor == uint64(u.Pos.LockBlockTid) {
				priceValue = value
				break
			}
		}
	}
	costItem := m.BaseKV{Key: int64(priceValue.GoodsId), Val: utils.Int64(priceValue.Num)}
	uProp, err = Cost(from, u, []m.BaseKV{costItem})
	if err != nil {
		return
	}

	uProp1, resGoods, boxResList, err := GiveGoodsByKv(from, u, m.BaseKV{Key: hsGoods.Goods.Tid, Val: hsGoods.Goods.Num}, PSend)
	if err != nil {
		return gid, uProp, resGoods, boxResList, err
	}
	gid = hsGoods.Goods.Tid
	hsGoods.Num -= num
	// 更新神秘商店信息
	hs.Update(hs)
	uProp.Merge(uProp1)
	return
}

func HideShopBuyGoodsAd(from string, u *m.User, id int64, num int64, code int64, PSend func(interface{}) error) (gid int64, uProp *m.UpdateProp, resGoods []*m.Goods, boxResList []*m.BoxRes, err error) {
	hs := u.HideShop()
	hsGoods, ok := hs.GetHideShopAdGoods(id)
	if !ok {
		err = errors.NewErrcode(data.Errcode.NotFound, "商城没有这个物品")
		return
	}

	if hsGoods.Num < num {
		err = errors.NewErrcode(data.Errcode.NoRes, "商城物品数量不足")
		return
	}

	uProp1, resGoods, boxResList, err := GiveGoodsByKv(from, u, m.BaseKV{Key: hsGoods.Goods.Tid, Val: hsGoods.Goods.Num}, PSend)
	if err != nil {
		return gid, uProp, resGoods, boxResList, err
	}

	gid = hsGoods.Goods.Tid
	hsGoods.Num -= num
	// 更新神秘商店信息
	hs.Update(hs)

	uProp = &m.UpdateProp{Kvs: make([]*m.BaseKV, 0)}
	uProp.Merge(uProp1)
	return
}
